//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package javax.vpncrypto;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StreamTokenizer;
import java.lang.reflect.Constructor;
import java.security.GeneralSecurityException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Vector;

final class CryptoPolicyParser {
    private Vector<CryptoPolicyParser.GrantEntry> grantEntries = new Vector();
    private StreamTokenizer st;
    private int lookahead;

    CryptoPolicyParser() {
    }

    void read(Reader var1) throws CryptoPolicyParser.ParsingException, IOException {
        if (!(var1 instanceof BufferedReader)) {
            var1 = new BufferedReader((Reader)var1);
        }

        this.st = new StreamTokenizer((Reader)var1);
        this.st.resetSyntax();
        this.st.wordChars(97, 122);
        this.st.wordChars(65, 90);
        this.st.wordChars(46, 46);
        this.st.wordChars(48, 57);
        this.st.wordChars(95, 95);
        this.st.wordChars(36, 36);
        this.st.wordChars(160, 255);
        this.st.whitespaceChars(0, 32);
        this.st.commentChar(47);
        this.st.quoteChar(39);
        this.st.quoteChar(34);
        this.st.lowerCaseMode(false);
        this.st.ordinaryChar(47);
        this.st.slashSlashComments(true);
        this.st.slashStarComments(true);
        this.st.parseNumbers();
        Object var2 = null;

        for(this.lookahead = this.st.nextToken(); this.lookahead != -1; this.match(";")) {
            if (!this.peek("grant")) {
                throw new CryptoPolicyParser.ParsingException(this.st.lineno(), "expected grant statement");
            }

            CryptoPolicyParser.GrantEntry var3 = this.parseGrantEntry((Hashtable)var2);
            if (var3 != null) {
                this.grantEntries.addElement(var3);
            }
        }

    }

    private CryptoPolicyParser.GrantEntry parseGrantEntry(Hashtable<String, Vector<String>> var1) throws CryptoPolicyParser.ParsingException, IOException {
        CryptoPolicyParser.GrantEntry var2 = new CryptoPolicyParser.GrantEntry();
        this.match("grant");
        this.match("{");

        while(!this.peek("}")) {
            if (!this.peek("Permission")) {
                throw new CryptoPolicyParser.ParsingException(this.st.lineno(), "expected permission entry");
            }

            CryptoPolicyParser.CryptoPermissionEntry var3 = this.parsePermissionEntry(var1);
            var2.add(var3);
            this.match(";");
        }

        this.match("}");
        return var2;
    }

    private CryptoPolicyParser.CryptoPermissionEntry parsePermissionEntry(Hashtable<String, Vector<String>> var1) throws CryptoPolicyParser.ParsingException, IOException {
        CryptoPolicyParser.CryptoPermissionEntry var2 = new CryptoPolicyParser.CryptoPermissionEntry();
        this.match("Permission");
        var2.cryptoPermission = this.match("permission type");
        if (var2.cryptoPermission.equals("javax.crypto.CryptoAllPermission")) {
            var2.alg = "CryptoAllPermission";
            var2.maxKeySize = 2147483647;
            return var2;
        } else {
            if (this.peek("\"")) {
                var2.alg = this.match("quoted string").toUpperCase(Locale.ENGLISH);
            } else {
                if (!this.peek("*")) {
                    throw new CryptoPolicyParser.ParsingException(this.st.lineno(), "Missing the algorithm name");
                }

                this.match("*");
                var2.alg = "*";
            }

            this.peekAndMatch(",");
            if (this.peek("\"")) {
                var2.exemptionMechanism = this.match("quoted string").toUpperCase(Locale.ENGLISH);
            }

            this.peekAndMatch(",");
            if (!this.isConsistent(var2.alg, var2.exemptionMechanism, var1)) {
                throw new CryptoPolicyParser.ParsingException(this.st.lineno(), "Inconsistent policy");
            } else {
                if (this.peek("number")) {
                    var2.maxKeySize = this.match();
                } else if (this.peek("*")) {
                    this.match("*");
                    var2.maxKeySize = 2147483647;
                } else {
                    if (!this.peek(";")) {
                        throw new CryptoPolicyParser.ParsingException(this.st.lineno(), "Missing the maximum allowable key size");
                    }

                    var2.maxKeySize = 2147483647;
                }

                this.peekAndMatch(",");
                if (this.peek("\"")) {
                    String var3 = this.match("quoted string");
                    Vector var4 = new Vector(1);

                    while(this.peek(",")) {
                        this.match(",");
                        if (this.peek("number")) {
                            var4.addElement(new Integer(this.match()));
                        } else {
                            if (!this.peek("*")) {
                                throw new CryptoPolicyParser.ParsingException(this.st.lineno(), "Expecting an integer");
                            }

                            this.match("*");
                            var4.addElement(new Integer(2147483647));
                        }
                    }

                    Integer[] var5 = new Integer[var4.size()];
                    var4.copyInto(var5);
                    var2.checkParam = true;
                    var2.algParamSpec = getInstance(var3, var5);
                }

                return var2;
            }
        }
    }

    private static final AlgorithmParameterSpec getInstance(String var0, Integer[] var1) throws CryptoPolicyParser.ParsingException {
        AlgorithmParameterSpec var2 = null;

        try {
            Class var3 = Class.forName(var0);
            Class[] var4 = new Class[var1.length];

            for(int var5 = 0; var5 < var1.length; ++var5) {
                var4[var5] = Integer.TYPE;
            }

            Constructor var7 = var3.getConstructor(var4);
            var2 = (AlgorithmParameterSpec)var7.newInstance((Object[])var1);
            return var2;
        } catch (Exception var6) {
            throw new CryptoPolicyParser.ParsingException("Cannot call the constructor of " + var0 + var6);
        }
    }

    private boolean peekAndMatch(String var1) throws CryptoPolicyParser.ParsingException, IOException {
        if (this.peek(var1)) {
            this.match(var1);
            return true;
        } else {
            return false;
        }
    }

    private boolean peek(String var1) {
        boolean var2 = false;
        switch(this.lookahead) {
            case -3:
                if (var1.equalsIgnoreCase(this.st.sval)) {
                    var2 = true;
                }
                break;
            case -2:
                if (var1.equalsIgnoreCase("number")) {
                    var2 = true;
                }
                break;
            case 34:
                if (var1.equals("\"")) {
                    var2 = true;
                }
                break;
            case 42:
                if (var1.equals("*")) {
                    var2 = true;
                }
                break;
            case 44:
                if (var1.equals(",")) {
                    var2 = true;
                }
                break;
            case 59:
                if (var1.equals(";")) {
                    var2 = true;
                }
                break;
            case 123:
                if (var1.equals("{")) {
                    var2 = true;
                }
                break;
            case 125:
                if (var1.equals("}")) {
                    var2 = true;
                }
        }

        return var2;
    }

    private int match() throws CryptoPolicyParser.ParsingException, IOException {
        int var1 = -1;
        int var2 = this.st.lineno();
        String var3 = null;
        switch(this.lookahead) {
            case -2:
                var1 = (int)this.st.nval;
                if (var1 < 0) {
                    var3 = String.valueOf(this.st.nval);
                }

                this.lookahead = this.st.nextToken();
                break;
            default:
                var3 = this.st.sval;
        }

        if (var1 <= 0) {
            throw new CryptoPolicyParser.ParsingException(var2, "a non-negative number", var3);
        } else {
            return var1;
        }
    }

    private String match(String var1) throws CryptoPolicyParser.ParsingException, IOException {
        String var2 = null;
        switch(this.lookahead) {
            case -3:
                if (var1.equalsIgnoreCase(this.st.sval)) {
                    this.lookahead = this.st.nextToken();
                } else {
                    if (!var1.equalsIgnoreCase("permission type")) {
                        throw new CryptoPolicyParser.ParsingException(this.st.lineno(), var1, this.st.sval);
                    }

                    var2 = this.st.sval;
                    this.lookahead = this.st.nextToken();
                }
                break;
            case -2:
                throw new CryptoPolicyParser.ParsingException(this.st.lineno(), var1, "number " + String.valueOf(this.st.nval));
            case -1:
                throw new CryptoPolicyParser.ParsingException("expected " + var1 + ", read end of file");
            case 34:
                if (var1.equalsIgnoreCase("quoted string")) {
                    var2 = this.st.sval;
                    this.lookahead = this.st.nextToken();
                } else {
                    if (!var1.equalsIgnoreCase("permission type")) {
                        throw new CryptoPolicyParser.ParsingException(this.st.lineno(), var1, this.st.sval);
                    }

                    var2 = this.st.sval;
                    this.lookahead = this.st.nextToken();
                }
                break;
            case 42:
                if (!var1.equals("*")) {
                    throw new CryptoPolicyParser.ParsingException(this.st.lineno(), var1, "*");
                }

                this.lookahead = this.st.nextToken();
                break;
            case 44:
                if (!var1.equals(",")) {
                    throw new CryptoPolicyParser.ParsingException(this.st.lineno(), var1, ",");
                }

                this.lookahead = this.st.nextToken();
                break;
            case 59:
                if (!var1.equals(";")) {
                    throw new CryptoPolicyParser.ParsingException(this.st.lineno(), var1, ";");
                }

                this.lookahead = this.st.nextToken();
                break;
            case 123:
                if (!var1.equals("{")) {
                    throw new CryptoPolicyParser.ParsingException(this.st.lineno(), var1, "{");
                }

                this.lookahead = this.st.nextToken();
                break;
            case 125:
                if (!var1.equals("}")) {
                    throw new CryptoPolicyParser.ParsingException(this.st.lineno(), var1, "}");
                }

                this.lookahead = this.st.nextToken();
                break;
            default:
                throw new CryptoPolicyParser.ParsingException(this.st.lineno(), var1, new String(new char[]{(char)this.lookahead}));
        }

        return var2;
    }

    javax.vpncrypto.CryptoPermission[] getPermissions() {
        Vector var1 = new Vector();
        Enumeration var2 = this.grantEntries.elements();

        while(var2.hasMoreElements()) {
            CryptoPolicyParser.GrantEntry var3 = (CryptoPolicyParser.GrantEntry)var2.nextElement();
            Enumeration var4 = var3.permissionElements();

            while(var4.hasMoreElements()) {
                CryptoPolicyParser.CryptoPermissionEntry var5 = (CryptoPolicyParser.CryptoPermissionEntry)var4.nextElement();
                if (var5.cryptoPermission.equals("javax.crypto.CryptoAllPermission")) {
                    var1.addElement(javax.vpncrypto.CryptoAllPermission.INSTANCE);
                } else if (var5.checkParam) {
                    var1.addElement(new javax.vpncrypto.CryptoPermission(var5.alg, var5.maxKeySize, var5.algParamSpec, var5.exemptionMechanism));
                } else {
                    var1.addElement(new javax.vpncrypto.CryptoPermission(var5.alg, var5.maxKeySize, var5.exemptionMechanism));
                }
            }
        }

        javax.vpncrypto.CryptoPermission[] var6 = new javax.vpncrypto.CryptoPermission[var1.size()];
        var1.copyInto(var6);
        return var6;
    }

    private boolean isConsistent(String var1, String var2, Hashtable<String, Vector<String>> var3) {
        String var4 = var2 == null ? "none" : var2;
        Vector var5;
        if (var3 == null) {
            var3 = new Hashtable();
            var5 = new Vector(1);
            var5.addElement(var4);
            var3.put(var1, var5);
            return true;
        } else if (var3.containsKey("CryptoAllPermission")) {
            return false;
        } else {
            if (var3.containsKey(var1)) {
                var5 = (Vector)var3.get(var1);
                if (var5.contains(var4)) {
                    return false;
                }
            } else {
                var5 = new Vector(1);
            }

            var5.addElement(var4);
            var3.put(var1, var5);
            return true;
        }
    }

    static final class ParsingException extends GeneralSecurityException {
        private static final long serialVersionUID = 7147241245566588374L;

        ParsingException(String var1) {
            super(var1);
        }

        ParsingException(int var1, String var2) {
            super("line " + var1 + ": " + var2);
        }

        ParsingException(int var1, String var2, String var3) {
            super("line " + var1 + ": expected '" + var2 + "', found '" + var3 + "'");
        }
    }

    private static class CryptoPermissionEntry {
        String cryptoPermission;
        String alg = null;
        String exemptionMechanism = null;
        int maxKeySize = 0;
        boolean checkParam = false;
        AlgorithmParameterSpec algParamSpec = null;

        CryptoPermissionEntry() {
        }

        public int hashCode() {
            int var1 = this.cryptoPermission.hashCode();
            if (this.alg != null) {
                var1 ^= this.alg.hashCode();
            }

            if (this.exemptionMechanism != null) {
                var1 ^= this.exemptionMechanism.hashCode();
            }

            var1 ^= this.maxKeySize;
            if (this.checkParam) {
                var1 ^= 100;
            }

            if (this.algParamSpec != null) {
                var1 ^= this.algParamSpec.hashCode();
            }

            return var1;
        }

        public boolean equals(Object var1) {
            if (var1 == this) {
                return true;
            } else if (!(var1 instanceof CryptoPolicyParser.CryptoPermissionEntry)) {
                return false;
            } else {
                CryptoPolicyParser.CryptoPermissionEntry var2 = (CryptoPolicyParser.CryptoPermissionEntry)var1;
                if (this.cryptoPermission == null) {
                    if (var2.cryptoPermission != null) {
                        return false;
                    }
                } else if (!this.cryptoPermission.equals(var2.cryptoPermission)) {
                    return false;
                }

                if (this.alg == null) {
                    if (var2.alg != null) {
                        return false;
                    }
                } else if (!this.alg.equalsIgnoreCase(var2.alg)) {
                    return false;
                }

                if (this.maxKeySize != var2.maxKeySize) {
                    return false;
                } else if (this.checkParam != var2.checkParam) {
                    return false;
                } else {
                    if (this.algParamSpec == null) {
                        if (var2.algParamSpec != null) {
                            return false;
                        }
                    } else if (!this.algParamSpec.equals(var2.algParamSpec)) {
                        return false;
                    }

                    return true;
                }
            }
        }
    }

    private static class GrantEntry {
        private Vector<CryptoPolicyParser.CryptoPermissionEntry> permissionEntries = new Vector();

        GrantEntry() {
        }

        void add(CryptoPolicyParser.CryptoPermissionEntry var1) {
            this.permissionEntries.addElement(var1);
        }

        boolean remove(CryptoPolicyParser.CryptoPermissionEntry var1) {
            return this.permissionEntries.removeElement(var1);
        }

        boolean contains(CryptoPolicyParser.CryptoPermissionEntry var1) {
            return this.permissionEntries.contains(var1);
        }

        Enumeration<CryptoPolicyParser.CryptoPermissionEntry> permissionElements() {
            return this.permissionEntries.elements();
        }
    }
}
